#pragma once
#include"log.hpp"
#include"InetAddr.hpp"
#include <string>
#include <cstring>
#include <sys/types.h>          
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <arpa/inet.h>

enum
{
    SOCKET_ERROR = 1,
    BIND_ERROR,
    USAGE_ERROR
};
class UdpServer
{
public:
    UdpServer(uint16_t port):_port(port),_running(false)
    {
        
    }
    //初始化UdpServer
    void InitServer()
    {
        //1.创建 Udp Stocket套接字
        _sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if(_sockfd < 0)
        {
            LOG(FATAL,"socket error,%s ,%d \n",strerror(errno),errno);
            exit(SOCKET_ERROR);
        }
        LOG(INFO,"socket create success,sockfd: %d\n",_sockfd);

        //2填充stockaddr_in结构
        struct sockaddr_in local;
        local.sin_family = AF_INET;
        //填充端口号，主机序列转网络序列
        local.sin_port = htons(_port);
        //填充ip，主机序列转网络序列 + 字符串风格ip转成点分十进制ip
        //local.sin_addr.s_addr = inet_addr(_ip.c_str());
        local.sin_addr.s_addr = INADDR_ANY;//inet_addr(INADDR_ANY); INADDR_ANY = 0.0.0.0
        //3 bind绑定端口
        int n = bind(_sockfd,(struct sockaddr*)&local,sizeof(local));
        if(n < 0)
        {
            LOG(FATAL,"bind error,%s ,%d \n",strerror(errno),errno);
            exit(BIND_ERROR);
        }
        LOG(FATAL,"socket bind success,sockfd: %d\n",_sockfd);
    }
    //启动UdpServer
    void Stat()
    {
        _running = true;
        //服务器一般都是死循环
        while(true)
        {
            sockaddr_in peer;
            //recvfrom的最后一个参数类型是socklen_t
            socklen_t len = sizeof(peer);
            char buffer[1024];
            //从接收缓存区中读取数据报
            int n  = recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)&peer,&len);
            //读取到数据才做处理，否则什么都不做
            if(n > 0)
            {
                buffer[n] = 0;
                //打印是哪个客户端发来的消息
                InetAddr addr(peer);
                LOG(INFO,"message form[%s:%d]: %s\n",addr.GetIp().c_str(),addr.Get_Port(),buffer);
                //将收到的数据发送给对方
                sendto(_sockfd,buffer,strlen(buffer),0,(sockaddr*)&peer,len);
            }
        }
        _running = false;
    }
    ~UdpServer()
    { }
private:
    int _sockfd;
    //std::string _ip;
    uint16_t _port;
    bool _running;
};